﻿namespace Microsoft.Tools.WixDeployment.Extensions
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Xml;
    using Microsoft.Tools.WindowsInstallerXml;

    public delegate void ParseElementNode(XmlNode node, Dictionary<string, string> result);

    /// <summary>
    /// Parses the XmlNode Element and its children.
    /// </summary>
    public class ElementNodeParser
    {
        Dictionary<string, ParseElementNode> factory;
        
        CompilerExtension compilerExtension;

        public ElementNodeParser(CompilerExtension compilerExtension, Dictionary<string, ParseElementNode> factory, Dictionary<string, ParseElementNode> rootFactory)
        {
            this.factory = factory;
            this.compilerExtension = compilerExtension;
        }

        public void Parse(XmlNode node, Dictionary<string, string> parentResult, params string[] validNodes)
        {
            if (validNodes == null) return;
            string parentPath = null;

            if (!parentResult.TryGetValue(Constants.ParentElementPath, out parentPath)) parentPath = "\\" + node.LocalName;

            foreach (XmlNode child in node.ChildNodes)
            {
                if (XmlNodeType.Element == child.NodeType)
                {
                    if (child.NamespaceURI != compilerExtension.Schema.TargetNamespace)
                    {
                        compilerExtension.Core.UnsupportedExtensionElement(node, child);
                    }

                    ParseElementNode parser = null;
                    string childPath = parentPath + "\\" + child.LocalName;
                    if (factory.TryGetValue(childPath, out parser))
                    {
                        parser(child, parentResult);
                    }
                    else
                    {
                        compilerExtension.Core.UnexpectedElement(node, child);
                    }                    
                }
            }
        }

        public bool TryGetValue(string elementName, out ParseElementNode parseElementNode)
        {
            return factory.TryGetValue("\\" + elementName, out parseElementNode);
        }
    }
}
